#include "comm_def.h"
#include "mz_file_info.h"
#include "mz_getopt.h"
#include "mz_debug.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <sys/stat.h>

typedef struct _INNER_MZ_NODE_T{
	MZ_NODE_T				 node;
	struct _INNER_MZ_NODE_T* next;
	struct _INNER_MZ_NODE_T* pre;
} INNER_MZ_NODE_T;

static INNER_MZ_NODE_T _mz_info_header;



static int _insert_node(char* path) {
	INNER_MZ_NODE_T* ptail = _mz_info_header.pre;
	INNER_MZ_NODE_T* pnew = (INNER_MZ_NODE_T*)malloc(sizeof(INNER_MZ_NODE_T));

	pnew->node.path = strdup(path);
	pnew->node.path_len = strlen(path);

	ptail->next = pnew;
	pnew->next = &_mz_info_header;
	_mz_info_header.pre = pnew;
	pnew->pre = ptail;
	return 0;
}


/*
define _A_NORMAL       0x00     Normal file - No read/write restrictions 
define _A_RDONLY       0x01     Read only file 
define _A_HIDDEN       0x02     Hidden file 
define _A_SYSTEM       0x04     System file 
define _A_SUBDIR       0x10     Subdirectory 
define _A_ARCH         0x20     Archive file 
*/
static void _print_attr_str(unsigned ui) {
	if (_A_NORMAL & ui) {
		printf("NORMAL");
	}
	if (_A_RDONLY & ui) {
		printf("RDONLY");
	}
	if (_A_HIDDEN & ui) {
		printf("HIDDEN");
	}
	if (_A_SYSTEM & ui) {
		printf("SYSTEM");
	}
	if (_A_SUBDIR & ui) {
		printf("SUBDIR");
	}
	if (_A_ARCH & ui) {
		printf("ARCH");
	}
}

static int _find_file_in_dir(char* dir) {
	long Handle;
	struct _finddata_t file_info;
	char fn[1024] = {0};

	sprintf(fn, "%s\\*.*", dir);
	if((Handle = _findfirst(fn , &file_info)) == -1L) {
	} else {
		if (0 != strcmp(".", file_info.name) && 0 != strcmp("..", file_info.name)) {
			printf("attr:0x%x:", file_info.attrib);
			_print_attr_str(file_info.attrib);
			printf(",size:%dByte,", file_info.size);
			printf("name:%s\n",file_info.name);
		}

		while( _findnext(Handle, &file_info) == 0) {
			if (0 != strcmp(".", file_info.name) && 0 != strcmp("..", file_info.name)) {
				printf("attr:0x%x:", file_info.attrib);
				_print_attr_str(file_info.attrib);
				printf(",size:%dByte,", file_info.size);
				printf("name:%s\\%s\n",dir, file_info.name);
				
				if (0 == (0x10 & file_info.attrib)) {
					unsigned int len = strlen(dir) + strlen(file_info.name) + 2;
					char* tmp = (char*)malloc(len);
					memset(tmp, 0, len);
					strcat(tmp, dir);
					strcat(tmp, "\\");
					strcat(tmp, file_info.name);
					_insert_node(tmp);
					free(tmp);
				}
				if (0x10 == file_info.attrib) {
					char fnsub[1024] = {0};
					sprintf(fnsub, "%s\\%s", dir, file_info.name);
					_find_file_in_dir(fnsub);
				}
			}
		}
		_findclose(Handle);
	}
	return 0;
}

int mz_make_file_info() {
	unsigned int i = 0;
	MZ_ARG_INFO* parg = get_arg_result("add");
	_mz_info_header.next = &_mz_info_header;
	_mz_info_header.pre = &_mz_info_header;

	for (; i < parg->param_cnt; ++i) {
		char** parr = (char**)parg->param_arr;
		struct stat st;

		int retst = stat(parr[i], &st);
		if (-1 == retst) {
			printf("get file:\"%s\" state FAILDED!.\n");
			return MZ_RESULT_NG;
		}
		if (st.st_mode & S_IFDIR) {
			_find_file_in_dir(parr[i]);
		} else if (S_IFREG & st.st_mode) {
			_insert_node(parr[i]);
		} else {
			printf("file:\"%s\" not Recognized!\n", parr[i]);
			return MZ_RESULT_NG;
		}		
	}
	return 0;
}

MZ_NODE_T* mz_get_file_list_info_first() {
	return &_mz_info_header.next->node;
}

MZ_NODE_T* mz_get_next_info(MZ_NODE_T* cur) {
	return (MZ_NODE_T*)((INNER_MZ_NODE_T*)cur)->next;
}

int mz_is_end_of_list(MZ_NODE_T* cur) {
	return &_mz_info_header == (INNER_MZ_NODE_T*)cur;
}


int mz_release_file_info() {
	INNER_MZ_NODE_T* it = _mz_info_header.next;
	while(&_mz_info_header != it) {
		INNER_MZ_NODE_T* tmp = it->next;
		free(it->node.path);
		free(it);
		it = tmp;
	}
	_mz_info_header.next = &_mz_info_header;
	_mz_info_header.pre = &_mz_info_header;
	return 0;
}
